<?php

/**
 * 抽象工厂：提供了一种封装具有【同一主题】的一组单独工厂的方法，而【无需指定他们的具体类】。
 * Class AbstractFactory: A factory of factories.
 * A factory that groups the individual but related/dependent factories together without specifying their concrete classes;
 */

// 门
interface Door2
{
    public function getDescription();
}

class WoodenDoor implements Door2
{
    public function getDescription()
    {
        echo "我是木门\n";
    }
}

class IronDoor implements Door2
{
    public function getDescription()
    {
        echo "我是铁门\n";
    }
}

// 安装专家
interface DoorFittingExpert
{
    public function getDescription();
}

class Welder implements DoorFittingExpert
{
    public function getDescription()
    {
        echo "我是木匠，只会修木门\n";
    }
}

class Carpenter implements DoorFittingExpert
{
    public function getDescription()
    {
        echo "我是铁匠，我只会修铁门\n";
    }
}

// door factory。
// 定义了多个工厂方法，实现相关或者依赖的组件
interface DoorFactory
{
    public function makeDoor():Door2;

    public function makeFittingExpert():DoorFittingExpert;
}

// 木门工厂方法
class WoodenDoorFactory implements DoorFactory
{
    public function makeDoor(): Door2
    {
        return new WoodenDoor();
    }

    public function makeFittingExpert(): DoorFittingExpert
    {
        return new Welder();
    }
}

class IronDoorFactory implements DoorFactory
{
    public function makeDoor(): Door2
    {
        return new IronDoor();
    }

    public function makeFittingExpert(): DoorFittingExpert
    {
        return new Carpenter();
    }
}

echo "木门\n";
$woodenFactory = new WoodenDoorFactory();
$door = $woodenFactory->makeDoor();
$expert = $woodenFactory->makeFittingExpert();
$door->getDescription();
$expert->getDescription();

echo "\n铁门\n";
$ironDoorFactory = new IronDoorFactory();
$door = $ironDoorFactory->makeDoor();
$expert = $ironDoorFactory->makeFittingExpert();
$door->getDescription();
$expert->getDescription();